<template>
    <div>
        注意越接近y=x越好,梯度下降算出的表达式为图中的表达式。
        训练次数<input type="text" v-model="k">
        <div id="main" style="width: 800px;height:600px;" ref="echarts">

        </div>
    </div>
</template>
<script>
import * as tf from '@tensorflow/tfjs'
import * as d3 from "d3";
export default {
    watch:{
        k(){
            this.echartSet();   
        }
    },
    data() {
        return {
            k: 300,
            x: tf.tensor2d([[],]),
            y: tf.tensor2d([[],]),
            w: tf.variable(tf.tensor([[]])),
            rw: [],
            roomData: {
                "House price (10,000 yuan)": [],
                "Room Squared (m2)": [],
                "Floors (floors)": [],
                "Age (years)": [],
                "Supporting elevators": []
            },
            markLineOpt: {
                animation: false,
                label: {
                    formatter: 'y = x ',
                    align: 'right'
                },
                lineStyle: {
                    type: 'solid'
                },
                tooltip: {
                    formatter: 'y = x '
                },
                data: [
                    [
                        {
                            coord: [0, 0],
                            symbol: 'none'
                        },
                        {
                            coord: [500, 500],
                            symbol: 'none'
                        }
                    ]
                ]
            }
            ,
            option: {
                title: {
                    text: "住房多变量线性回归",
                    left: 'center',
                    top: 0
                },
                grid: [
                    { left: '7%', top: '7%', width: '80%', height: '80%' },
                ],
                tooltip: {
                    formatter: 'Group {a}: ({c})'
                },
                xAxis: [
                    { gridIndex: 0, min: 0, max: 500 },
                ],
                yAxis: [
                    { gridIndex: 0, min: 0, max: 500 },
                ],
                series: [
                    {
                        name: 'I',
                        type: 'scatter',
                        xAxisIndex: 0,
                        yAxisIndex: 0,
                        data: [],
                        markLine: {},
                    },
                ]
            }
        }
    },
    methods: {
        echartSet: async function () {
            var myCharts = this.$echarts.init(this.$refs.echarts);
            await this.dataSet()
            var xArray = await this.w.matMul(this.x).dataSync();
            var yArray = await this.y.dataSync();
            var w=await this.w.dataSync();
            var data = [];
            for (var i = 0; i < xArray.length; i++) {
                data.push([xArray[i], yArray[i]]);
            }
            this.option.series[0].data=data;
            var str="y=";
            for(var i=0;i<w.length;i++){
                str+=`${w[i].toFixed(2)}(x${i})`
            }
            this.markLineOpt.label.formatter=str;
            this.option.series[0].markLine=this.markLineOpt;
            myCharts.setOption(this.option);
        },
        dataSet: async function () {
            var { datax, datay, roomData, dataxCount } = await this.getData()
            this.roomData = roomData;
            this.x = tf.tensor(datax)
            this.y = tf.tensor(datay)
            this.w = tf.variable(tf.tensor([new Array(dataxCount - 1).fill(0)]))
            this.train(this.x, this.y, this.k);
            this.$emit("data",roomData);
        },
        getData: async function () {
            var datax = [];
            var datay = [];
            var roomData = {
                "House price (10,000 yuan)": [],
                "Room Squared (m2)": [],
                "Floors (floors)": [],
                "Age (years)": [],
                "Supporting elevators": []
            }
            await d3.csv("./住房/线性回归.csv", function (data, error) {
                for (var name in data) {
                    roomData[name].push(parseInt(data[name]));
                }
            })
            var dataxCount = 0;
            for (var name in roomData) {
                dataxCount++;
                if (name != "House price (10,000 yuan)") datax.push(roomData[name])
                else datay.push(roomData[name])
            }
            return { datax, datay, roomData, dataxCount };
        },
        predict(x) {
            /* 
              y = [[w0,w1,w2]]*[
                              [125,29],
                              [256,8000],
                              [6000,32000]
                            ]
            */
            return tf.tidy(() => {

                return this.w.matMul(x);
            });
        },
        loss(predictions, labels) {
            // 将labels（实际的值）进行抽象
            // 然后获取平均数.
            const meanSquareError = predictions.sub(labels).square().mean();
            return meanSquareError;
        },
        train(x, y, numIterations) {

            const learningRate = 0.000001;  //学习率
            const optimizer = tf.train.sgd(learningRate);

            for (let iter = 0; iter < numIterations; iter++) {
                optimizer.minimize(() => {
                    const predsYs = this.predict(x);
                    return tf.losses.meanSquaredError(predsYs,y);
                });
            }
        },
        tensorTran: function (w) {
            var data = w.dataSync();
            return data;
        }
    },
    mounted: async function() {
        this.echartSet();
        
    }
}
</script>
<style lang="less" scoped></style>